﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using NearForums.Web.Controllers.Filters;
using NearForums.Services;
using NearForums.Web.Extensions;
using NearForums.Validation;
using System.Web.Security;
using NearForums.Web.Controllers.Helpers;
using System.Collections;
using System.Web;
using System.IO;
using System.Globalization;
using System.Drawing;

namespace NearForums.Web.Controllers
{
	public class UsersController : BaseController
	{
		/// <summary>
		/// User service
		/// </summary>
		private readonly IUsersService _service;

		/// <summary>
		/// Topic service
		/// </summary>
		private readonly ITopicsService _topicService;

		public UsersController(IUsersService service, ITopicsService topicService) : base(service)
		{
			_service = service;
			_topicService = topicService;
		}

		public ActionResult Detail(int id)
		{
			User user = _service.Get(id);
			if (user == null)
			{
				return ResultHelper.NotFoundResult(this);
			}
			//Get posted topics
			ViewData["Topics"] = _topicService.GetByUser(id, Role);

			return View(user);
		}

		[RequireAuthorization(UserRole.Admin)]
		public ActionResult List(string userName, int page)
		{
			List<User> users = null;
			if (String.IsNullOrEmpty(userName))
			{
				users = _service.GetAll();
			}
			else
			{
				users = _service.GetByName(userName);
			}
			ViewBag.UserName = userName;
			ViewBag.Page = page;

			return View(users);
		}

		public ActionResult MessagesByUser(int id)
		{
			User user = _service.Get(id);
			if (user == null)
			{
				return ResultHelper.NotFoundResult(this);
			}
			//Get posted messages (ordered 
			var topics = _topicService.GetTopicsAndMessagesByUser(id);
			return View(false, topics);
		}

		#region Edit
		[RequireAuthorization]
		[HttpGet]
		public ActionResult Edit(int id)
		{
			if (this.User.Id != id)
			{
				//Maybe handle a moderator/admin users
				return ResultHelper.ForbiddenResult(this);
			}
			var user = _service.Get(id);
			return View(user);
		}

		[RequireAuthorization]
		[HttpPost]
		public ActionResult Edit(int id, [Bind(Prefix = "")]User user)
		{
			if (this.User.Id != id)
			{
				//Future: Maybe handle a moderator/admin users
				return ResultHelper.ForbiddenResult(this);
			}
			try
			{
				user.Id = id;
				_service.Edit(user);

				//Update membership data
				if (Session.User.Provider == AuthenticationProvider.Membership && !String.IsNullOrEmpty(user.Email))
				{
					if (HttpContext.User.Identity.Name == "")
					{
						throw new Exception("Identity can not be null.");
					}
					var membershipUser = MembershipProvider.GetUser(HttpContext.User.Identity.Name, false);
					membershipUser.Email = user.Email;
					MembershipProvider.UpdateUser(membershipUser);
				}

				this.User.UserName = user.UserName;
				this.User.Email = Utils.EmptyToNull(user.Email);

				return RedirectToAction("Detail", new { id = id });
			}
			catch (ValidationException ex)
			{
				this.AddErrors(this.ModelState, ex);
			}
			return View(user);
		}
		#endregion

		#region Promote / Demote / Delete
		[RequireAuthorization(UserRole.Admin)]
		[HttpPost]
		[ValidateAntiForgeryToken]
		public ActionResult Promote(int id, string searched)
		{
			_service.Promote(id);
			return RedirectToAction("List", new
			{
				userName = searched,
				page = 0
			});
		}

		[RequireAuthorization(UserRole.Admin)]
		[HttpPost]
		[ValidateAntiForgeryToken]
		public ActionResult Demote(int id, string searched)
		{
			_service.Demote(id);
			return RedirectToAction("List", new
			{
				userName = searched,
				page = 0
			});
		}

		[RequireAuthorization(UserRole.Admin)]
		[HttpPost]
		[ValidateAntiForgeryToken]
		public ActionResult Delete(int id, string searched)
		{
			_service.Delete(id);
			return RedirectToAction("List", new
			{
				userName = searched,
				page = 0
			});
		}
		#endregion


        #region UserImage Edit
        /// <summary>
        /// 头像上传
        /// </summary>
        /// <returns></returns>
        public ActionResult UploadFile()
        {
            String aspxUrl = Request.Path.Substring(0, Request.Path.LastIndexOf("/") + 1);
            HttpPostedFileBase imgFile = Request.Files["imgFile"];
            String dirName = Request.QueryString["dir"];

            return UploadValidate(aspxUrl, imgFile, dirName, 120);

        }

        public ActionResult UploadCoverFile()
        {
            String aspxUrl = Request.Path.Substring(0, Request.Path.LastIndexOf("/") + 1);
            HttpPostedFileBase imgFile = Request.Files["imgFile"];
            String dirName = Request.QueryString["dir"];

            return UploadValidate(aspxUrl, imgFile, dirName, 800);

        }


        private ActionResult UploadValidate(string aspxUrl, HttpPostedFileBase imgFile, string dirName, int maxWidth)
        {
            //文件保存目录路径
            String savePath = "../userAttached/";

            //文件保存目录URL
            String saveUrl = aspxUrl + "../userAttached/";

            //定义允许上传的文件扩展名
            Hashtable extTable = new Hashtable();
            extTable.Add("image", "gif,jpg,jpeg,png,bmp");

            //最大文件大小
            int maxSize = 1000000;

           
            if (imgFile == null)
            {
                return GetError("请选择文件。");
            }

            String dirPath = Server.MapPath(savePath);
            if (!Directory.Exists(dirPath))
            {
                return GetError("上传目录不存在。");
            }

            
            if (String.IsNullOrEmpty(dirName))
            {
                dirName = "image";
            }
            if (!extTable.ContainsKey(dirName))
            {
                return GetError("目录名不正确。");
            }

            String fileName = imgFile.FileName;
            String fileExt = Path.GetExtension(fileName).ToLower();

            if (imgFile.InputStream == null || imgFile.InputStream.Length > maxSize)
            {
                return GetError("上传文件大小超过限制。");
            }

            if (String.IsNullOrEmpty(fileExt) || Array.IndexOf(((String)extTable[dirName]).Split(','), fileExt.Substring(1).ToLower()) == -1)
            {
                return GetError("上传文件扩展名是不允许的扩展名。\n只允许" + ((String)extTable[dirName]) + "格式。");
            }

            System.Drawing.Image img = System.Drawing.Image.FromStream(imgFile.InputStream, false);
            //缩放图片      
            if(img.Width>maxWidth)
                img = GetOutputSizeImage(img, maxWidth);

            //创建文件夹
            dirPath += dirName + "/";
            saveUrl += dirName + "/";
            if (!Directory.Exists(dirPath))
            {
                Directory.CreateDirectory(dirPath);
            }
            String ymd = DateTime.Now.ToString("yyyyMMdd", DateTimeFormatInfo.InvariantInfo);
            dirPath += ymd + "/";
            saveUrl += ymd + "/";
            if (!Directory.Exists(dirPath))
            {
                Directory.CreateDirectory(dirPath);
            }

            String newFileName = DateTime.Now.ToString("yyyyMMddHHmmss_ffff", DateTimeFormatInfo.InvariantInfo) + fileExt;
            String filePath = dirPath + newFileName;

            img.Save(filePath);
            //imgFile.SaveAs(filePath);

            String fileUrl = saveUrl + newFileName;

            Hashtable hash = new Hashtable();
            hash["error"] = 0;
            hash["url"] = fileUrl;
            return Json(hash, "text/html;charset=UTF-8");
 
        }

        private ActionResult GetError(string message)
        {
            Hashtable hash = new Hashtable();
            hash["error"] = 1;
            hash["message"] = message;

            return Json(hash, "text/html;charset=UTF-8");
        }

        private Image GetOutputSizeImage(Image imgSource, int MAX_WIDTH)
        {
            Image imgOutput = imgSource;

            Size size = new Size(imgSource.Width, imgSource.Height);
            if (imgSource.Width <= 3 || imgSource.Height <= 3) return imgSource; //3X3大小的图片不转换 

            if (imgSource.Width > MAX_WIDTH || imgSource.Height > MAX_WIDTH)
            {
                double rate = MAX_WIDTH / (double)imgSource.Width;

                if (imgSource.Height * rate > MAX_WIDTH)
                    rate = MAX_WIDTH / (double)imgSource.Height;

                size.Width = Convert.ToInt32(imgSource.Width * rate);
                size.Height = Convert.ToInt32(imgSource.Height * rate);

                imgOutput = imgSource.GetThumbnailImage(size.Width, size.Height, null, IntPtr.Zero);
            }

            return imgOutput;
        }

        #endregion
    }
}